前一篇第 7 天是提到「在 SwiftUI 如何實作多欄位 List - LazyVGrid 與 GridItem」,雖然本系列文章基本上沒有前後關聯,如果你是還沒讀過前一篇的讀者,也推薦你去讀讀。
Safe Area 是 Apple 為了解決 iPhone 有瀏海 (notch) 或後來的動態島、圓角螢幕等導致螢幕有部分不適合互動或顯示,而提出的畫面佈局機制。
所以在官方的建議在預設情形之下,畫面盡可能地在 Safe Area 內顯示。
但是在不同情境下,我們仍然有需要和 Safe Area 打交道,這時候就可以用到 safeAreaInset 。例如這樣子的 UI :
我們先做一個簡單的 List ,這個畫面用 Scroll View
顯示了一個清單,並包含了一些基本樣式和按鈕
struct ContentView: View {
var body: some View {
ScrollView {
ForEach(0..<30, id:\.self) { episode in
HStack(alignment:.center) {
Text("Day \(episode)")
Spacer()
buttons()
}
.padding(.vertical, 8)
.padding(.horizontal)
}
.frame(maxWidth: .infinity)
}
}
private func buttons() -> some View {
HStack(spacing: 8) {
Button {} label: {
Image(systemName: "heart")
}
.foregroundColor(Color.pink)
Button {} label: {
Image(systemName: "bookmark")
}
.foregroundColor(Color.blue)
}
}
}
執行或在 Xcode 裡預覽後,畫面就會像這樣:
在初始的程式碼加上一段
.safeAreaInset(edge: .bottom) { /* ... */ }
就能夠在畫面的下半部加上自己想要的 UI ,並設定背景
struct ContentView: View {
var body: some View {
ScrollView {
ForEach(0..<30, id:\.self) { episode in
HStack(alignment:.center) {
Text("Day \(episode)")
Spacer()
buttons()
}
.padding(.vertical, 8)
.padding(.horizontal)
}
.frame(maxWidth: .infinity)
}
// 從這裡
.safeAreaInset(edge: .bottom) {
HStack {
Spacer()
Button {} label: {
Text("鐵人發文")
.font(.system(size: 14, weight: .bold))
.padding()
}
.foregroundColor(.teal)
.background(
RoundedRectangle(cornerRadius: 10)
.foregroundColor(.white)
)
.padding(.vertical)
.padding(.horizontal, 24)
}
.frame(maxWidth: .infinity)
.background(Color.teal)
}
// 到這裡
}
private func buttons() -> some View { /* 省略 */ }
}
在上面的程式碼我們把參數 edge 設定為 .bottom
。當然如果有需要也可以設為其他邊界,例如 .top
,就會很像一個 Navigation Bar 的效果了:
到這裡就是在 SwiftUI 該如何使用 safeAreaInset 。如果有疑問、回饋,歡迎留言討論~
那今天的 SwiftUI 的大大小小就到這邊,以上,明天見!
本篇使用到的 UI 元件和 modifiers 基本上沒有受到版本更新影響,
因此 Xcode 14 等環境下使用也是沒問題的。